#include "priv/atkconnmanager.hxx"
#include "priv/atkconn.hxx"
#include <tcpsocket.hxx>
#include <myfilelog.hxx>
#include <loghelper.hxx>
#include <tcpbridgenet.hxx>
#include <utility.hxx>
#include <macro.hxx>

    AtkConn::AtkConn(AtkConnManager* manager, TcpSocket *remote, FileLog *filelog)
: Thread(),
    _manager(manager),
    _bmsg_que(),
    _remote(remote),
    _bridgenet(NULL),
    _shutdown_requested(false),
    _filelog(filelog)
{
}

AtkConn::~AtkConn()
{
    if (_remote)
    {
        delete _remote;
        _remote=0;
    }
    if (_bridgenet)
    {
        delete _bridgenet;
        _bridgenet=0;
    }
}
void AtkConn::Shutdown()
{
    _shutdown_requested=true;
}

void AtkConn::SendMsg(tBridgeMsg* bmsg)
{
    _bmsg_que.Push(bmsg);
}

bool AtkConn::HandleOut(void)
{
    if (0 >= _bridgenet->IsReadyForWrite())
    {
        Yield();
        return false;
    }

    tBridgeMsg* bmsg = _bmsg_que.Pop();
    if (!bmsg)
        return false;

    if(_bridgenet->SendMsg(bmsg))
    {
        APPENDMSGEX("AtkConn: #"<<Id()<<" message sent successfully.", 0);
    }
    else
    {
        APPENDMSGEX("AtkConn: #"<<Id()<<" failed to send message.", 3);
    }

    ReleaseBMsg(bmsg);

    return true;
}

bool AtkConn::HandleIn()
{
    tBridgeMsg* bmsg;

    BridgeNet::tBridgeNetStatus res;

    if (0 >= _bridgenet->IsReadyForRead(100))
        return false;

    res=_bridgenet->ReceiveMsg(&bmsg);

    switch(res)
    {
        case BridgeNet::eMsgAvailable:
            {
                // within the same thread.
                APPENDMSGEX("AtkConn: #"<<Id()<<" received a message from "<<_bridgenet->PeerHostAddress()<<":"<<_bridgenet->PeerHostPort(), 0);

                HandleMsg(bmsg);
            }
            break;

        case BridgeNet::eMsgNotAvailable:
            {
                //not clear
                LOGWARNING("AtkConn: #"<<Id()<<" received a not available from.");
            }
            break;

        case BridgeNet::eEndOfConnectionReceived:
            {
                APPENDMSGEX("AtkConn: #"<<Id()<<" received end of connection signal.", 0);
                Shutdown();
            }
            break;

        case BridgeNet::eNetworkErrorReceived:
            {
                LOGWARNING("AtkConn: #"<<Id()<<" received network error.");
                Shutdown();
            }
            break;

        default:
            {
                LOGERROR("AtkConn: #"<<Id()<<": Unexpected returned value "<<res<<".");
                Shutdown();
            }
            break;
    } // switch(res)

    return true;
}

void AtkConn::Execute(Arg arg)
{
    APPENDMSGEX("AtkConn #"<<Id()<<" started.", 0);

    _bridgenet = new TcpBridgeNet(_remote, _filelog);
    
    while (!_shutdown_requested)
    {
        HandleIn();
        HandleOut();
        
        Yield();
    }

    delete _bridgenet;
    _bridgenet = 0;

    APPENDMSGEX("AtkConn #"<<Id()<<" shutdowned.", 0);
}

const string& AtkConn::PeerHostAddress() const
{
    return _remote->PeerHostAddress();
}
unsigned short AtkConn::PeerHostPort() const
{
    return _remote->PeerHostPort();
}

bool AtkConn::HandleMsg(tBridgeMsg* bmsg)
{
    tByte* msg;
    tUInt32 len;
    tUInt32 mpi = 0;
    tUInt32 tom = E_WAS_MSG_CJHR_RSP;
    tUInt32 tid = 0;
    tUInt32 rspc = X_WAS_RSPC_NONE;

    tBridgeMsg* brspmsg;

    switch (bmsg->tom)
    {
        case E_WAS_MSG_CJHR_REQ:
            {
		APPENDMSGEX("Request Cjh...", 0);
                string cjhRoot, clxh;
                _manager->GetCjhRoot(cjhRoot, clxh);

                msg = was_write_msg(&len, mpi, tom, tid, rspc,
                        E_WAS_TAG_ID_CJHR, cjhRoot.length(), cjhRoot.c_str(),
                        E_WAS_TAG_ID_CLXH, clxh.length(), clxh.c_str(),
                        E_WAS_TAG_ID_NONE);

                brspmsg = CreateBMsg();
                brspmsg->lom = len;
                brspmsg->mpi = mpi;
                brspmsg->tom = tom;
                brspmsg->tid = tid;
                brspmsg->rspc = rspc;
                brspmsg->msg = msg;

                SendMsg(brspmsg);
            }
            break;
        default:
            APPENDMSGEX("AtkConn #"<<Id()<<" HandleMsg unknown tom "<<bmsg->tom<<"!!!", 3);
            break;
    }

    ReleaseBMsg(bmsg);
    
    return true;
}
